using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Collections.Generic;
using FwkLight.CodeExtensions;
using FwkLight.Web;
using StructureMap;

namespace FwkLight.Application.Caching
{
  public class CacheItemDictionary: ICacheItemDictionary
  {
    private readonly Cache _cache = HttpRuntime.Cache;
    private readonly int _cachingTimeInHours = ApplicationConstants.Caching.DefaultCachingTimeInHours;
    private const string NULLInCache = "NULL";

    //private IList<ITaskCacheDependency> CacheDependencies
    //{
    //  get
    //  {
    //    IList<ITaskCacheDependency> dependencies = Get(ApplicationConstants.Caching.CacheDependencies);
    //    if (dependencies == null)
    //    {
    //      dependencies = new List<ITaskCacheDependency>();
    //      ICacheDependencyConfig cacheDependencyConfig = ObjectFactory.With("taskCacheDependencies").EqualTo(dependencies).GetInstance<ICacheDependencyConfig>();
    //      if (cacheDependencyConfig != null)
    //      {
    //        cacheDependencyConfig.Configure();
    //        Add(ApplicationConstants.Caching.CacheDependencies, dependencies);
    //      }
    //    }

    //    return dependencies;
    //  }
    //}

    public void Add<ItemToPutInContext> ( IItemKey<ItemToPutInContext> key, ItemToPutInContext item )
    {
      if (item == null)
        _cache.Insert(key.Key, NULLInCache, null, DateTime.Now.AddHours(_cachingTimeInHours),
                      Cache.NoSlidingExpiration);
      else _cache.Insert( key.Key, item, null, DateTime.Now.AddHours(_cachingTimeInHours),
                          Cache.NoSlidingExpiration );
    }

    public void Add<ItemToPutInContext>(IItemKey<ItemToPutInContext> key, ItemToPutInContext item, int cachingTimeInHours)
    {
      if (item == null)
        _cache.Insert(key.Key, NULLInCache, null, DateTime.Now.AddHours(cachingTimeInHours), Cache.NoSlidingExpiration);
      else
        _cache.Insert(key.Key, item, null, DateTime.Now.AddHours(cachingTimeInHours), Cache.NoSlidingExpiration);
    }

    public Item Get<Item> ( IItemKey<Item> key )
    {
      if (_cache[key.Key] == null)
      {
        return default(Item);
      }

      if (_cache[key.Key].ToString() == NULLInCache)
        return default(Item);

      return (Item)_cache[key.Key ];
    }

    public bool Contains<Item>(IItemKey<Item> key)
    {
      return _cache.Get(key.Key) != null;
    }

    public void Remove<ItemToPutIn>(IItemKey<ItemToPutIn> key)
    {
      _cache.Remove(key.Key);
    }

    public void Remove<TaskType>(string cacheVariation) where TaskType: IApplicationTask
    {
      string cacheKey = ApplicationTask.CacheKey(typeof(TaskType).Name, cacheVariation);
      _cache.Remove(cacheKey);
    }

    //public void RemoveByPartialKey<TaskType>(string cachePartialVariation) where TaskType : IApplicationTask
    //{
    //  //string cacheKey = ApplicationTask.CacheKey(typeof(TaskType).Name, cachePartialVariation);
    //  //_cache.Remove(cacheKey);
    //  IDictionaryEnumerator en = _cache.GetEnumerator();
    //  while(en.MoveNext())
    //  {
    //    string key = en.Key.ToString();
    //    if (key.Contains(typeof(TaskType).Name) && key.Contains(cachePartialVariation))
    //      _cache.Remove(key);
    //  }
    //}

    public void ClearCache()
    {
      IList<string> cacheItems = new List<string>();
      IDictionaryEnumerator enumerator = _cache.GetEnumerator();
      while(enumerator.MoveNext())
        cacheItems.Add(enumerator.Key.ToString());

      foreach (string item in cacheItems)
        _cache.Remove(item);
    }

    //public void UpdateCacheForExecutedTask<T>(IApplicationTask<T> task)
    //{
    //  var dependencies = GetDependenciesForUpdate(task);
    //  dependencies
    //    .ForEach(u => _cache.Remove(ApplicationTask.CacheKey(u.DependentType.Name, task.CacheResetVariation)));
    //}

    //public IEnumerable<ITaskCacheDependency> GetDependenciesForUpdate<T>(IApplicationTask<T> task)
    //{
    //  return CacheDependencies
    //    .Where(p => p.ActionType.Equals(task.GetType()));
    //}
  }
}